#include "Task.hpp"
#include <string>
#include <vector>
#include <unistd.h>
#include<assert.h>
#include<cstdlib>
#include<ctime>
#include <sys/wait.h>

const int processnum = 5;
std::vector<task_t> tasks;

// 先描述
class channel
{
public:
    channel(int cmdfd,int slaverid,std::string processname)
    :_cmdfd(cmdfd),_slaverid(slaverid),_processname(processname)
    {}
public:
    int _cmdfd;               // 发送任务的文件描述符
    pid_t _slaverid;          // 子进程的pid
    std::string _processname; // 子进程的名字 --方便我们打印日志
};
//child
void slaver()
{
    while(true)
    {
        int cmdcode=0;
        int n=read(0,&cmdcode,sizeof(int));
        if(n==sizeof(int))
        {
            std::cout<<"slaver say@ get a command: "<<getpid()<<"-"<<" cmdcode: "<<cmdcode<<std::endl;
            if(cmdcode>=0&&cmdcode<tasks.size()) tasks[cmdcode]();
        }
        if(n==0)
        {
            std::cout<<"child process quit "<<getpid()<<std::endl;

            break;
        }
    }
}
// 输入：const &
// 输出：*
// 输入输出：&
void InitProcessPool(std::vector<channel>* channels)
{
    // std::vector<int> odlfd;
    for (int i = 0; i < processnum; i++)
    {
        int pipefd[2];//临时空间
        int n=pipe(pipefd);
        assert(!n);
        (void)n;
        pid_t id = fork();
        if(id==0)//child
        {
            // std::cout<<"child: "<<getpid()<<"close histroy ";
            // for(auto fd: odlfd) {
            //     std::cout<<fd<<" ";
            //     close(fd);
            // }
            std::cout<<std::endl;
            close(pipefd[1]);
            dup2(pipefd[0],0);
            close(pipefd[0]);
            slaver();

            exit(0);
        }
        //father
        close(pipefd[0]);
        //添加channel字段
        std::string name=" process: "+std::to_string(i);
        channels->push_back(channel(pipefd[1],id,name));
        // odlfd.push_back(pipefd[1]);
        sleep(1);
    }
}
void Debug(const std::vector<channel>& channels )
{
    for(auto& c:channels)
    {
        std::cout<<c._cmdfd<<" "<<c._slaverid<<" "<<c._processname<<" "<<std::endl;
    }
}

void ctrlSlaver(const std::vector<channel>& channels)
{
    int which=0;
    int cnt=5;
    while(cnt)
    {
        //1.选择任务
        int cmdcode=rand()%tasks.size();
        //2.选择进程
        //int processpos=rand()%channels.size();

        std::cout<<"father say: "<<" cmdcode: "<<
        cmdcode<<" already sendto "<<channels[which]._slaverid<<" process name "<<channels[which]._processname<<std::endl;
        //3.发送任务
        write(channels[which]._cmdfd,&cmdcode,sizeof(cmdcode));
        which++;
        which%=channels.size();
        cnt--;
        sleep(1);
    }
}
    
void QuitProcess(std::vector<channel> channels)
{
    for(const auto& c: channels) {
        close(c._cmdfd);
        waitpid(c._slaverid,nullptr,0);
    }
    //sleep(5);
    //for(const auto& c: channels) waitpid(c._slaverid,nullptr,0);
   // sleep(5);
}

int main()
{
    LoadTask(&tasks);
    srand(time(nullptr)^getpid()^1023);
    // 在组织
    std::vector<channel> channels;
    // 初始化
    InitProcessPool(&channels);
    //Debug(channels);
    //2.开始控制子进程
    ctrlSlaver(channels);
    //清理收尾
    QuitProcess(channels);
    return 0;
}